package com.module.ble.utils

import com.common.app.utls.TimeUtils
import com.common.base.app.extras.formatToFloat
import com.common.base.utils.AppUtils.getString
import com.common.base.utils.ViewUtils
import com.module.ble.R
import com.module.ble.data.bean.CusChartData
import com.module.ble.data.bean.CusUnifyData
import com.module.ble.db.table.UserBloodOxygen
import com.module.ble.db.table.UserHeartRate
import com.module.ble.db.table.UserSleepInfo
import java.util.Calendar
import kotlin.random.Random

/**
 *
 * 作者：sosou
 *
 * 版本：1.0
 *
 * 创建日期：2025/3/27
 *
 * 描述：
 *
 * 修订历史：
 *
 */
object BleOtherUtil {

    val allHeartRates = mutableListOf<UserHeartRate>()//测试用
    val allSleepInfo = mutableListOf<UserSleepInfo>()//测试用

    /**
     * 使用ThreadLocal Calendar以避免多线程问题
     */
    private val calendarThreadLocal : ThreadLocal<Calendar> = ThreadLocal<Calendar>()

    private fun getThreadLocalCalendar(): Calendar {
        return calendarThreadLocal.get() ?: Calendar.getInstance().also {
            calendarThreadLocal.set(it)
        }
    }

    fun removeThreadLocalCalendar() {
        calendarThreadLocal.remove()
    }


    /**
     * 检查心率值是否在有效范围内
     */
    private fun isValidHeartRate(heartRate: Float): Boolean =
        heartRate in BleConfig.MIN_VALID_HEART_RATE..BleConfig.MAX_VALID_HEART_RATE

    /**
     * 计算距离当天开始的分钟数
     */
    private fun calculateMinutesFromDayStart(calendar: Calendar): Int =
        calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE)

    /**
     * 设置日历为当天开始时间
     */
    private fun Calendar.setStartOfDay() {
        set(Calendar.HOUR_OF_DAY, 0)
        set(Calendar.MINUTE, 0)
        set(Calendar.SECOND, 0)
        set(Calendar.MILLISECOND, 0)
    }

    /**
     *  根据当前周返回天的全基类数据
     */
    fun createWeekTemplateData(): List<CusChartData> {
        val chartData = mutableListOf<CusChartData>()
        // 获取本周一的起始时间
        val calendar = Calendar.getInstance()
        // 确保周一是一周的第一天
        calendar.firstDayOfWeek = Calendar.MONDAY
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY)
        calendar.set(Calendar.HOUR_OF_DAY, 0)
        calendar.set(Calendar.MINUTE, 0)
        calendar.set(Calendar.SECOND, 0)
        calendar.set(Calendar.MILLISECOND, 0)

        val mondayTime = calendar.timeInMillis

        // 使用循环创建一周七天的数据
        for (dayOffset in 0..6) {
            // 为每天创建一个新的 Calendar 实例
            val dayCalendar = Calendar.getInstance()
            dayCalendar.timeInMillis = mondayTime
            dayCalendar.add(Calendar.DAY_OF_MONTH, dayOffset)
            chartData.add(
                CusChartData(
                    createdTime = dayCalendar.timeInMillis,
                    mValue = 0f,
                    minValue = 0f
                )
            )
        }

        return chartData
    }

    /**
     *  根据当前月返回天的全基类数据
     */
    fun loadMonthData(year: Int, month: Int): List<CusChartData> {
        val calendar = Calendar.getInstance()
        calendar.set(year, month - 1, 1) // month是1-12
        val daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH)

        return List(daysInMonth) { dayIndex ->
            calendar.set(year, month - 1, dayIndex + 1)
            CusChartData(
                createdTime = calendar.timeInMillis,
                mValue = 0f,
                minValue = 0f,
                dayNum = TimeUtils.getDayOfMonthLegacy(calendar.timeInMillis)
            )
        }
    }



    /**
     * 检查时间戳是否在目标日期内
     */
    private fun isValidTimestamp(timestamp: Long, targetTime: Long): Boolean {
        val calendar = getThreadLocalCalendar()

        calendar.timeInMillis = targetTime
        val targetYear = calendar.get(Calendar.YEAR)
        val targetDayOfYear = calendar.get(Calendar.DAY_OF_YEAR)

        calendar.timeInMillis = timestamp

        return calendar.get(Calendar.YEAR) == targetYear &&
                calendar.get(Calendar.DAY_OF_YEAR) == targetDayOfYear
    }


    /**
     * 将心率数据转换为图表数据
     * @param heartRateList 心率数据列表
     * @param targetDate 目标日期时间戳
     * @param forceToday 是否强制转换为今天的数据
     * @return Pair<图表数据列表, 平均值>
     */
    fun <T : CusUnifyData> convertToChartData(
        dataList: List<T>,
        targetDate: Long = System.currentTimeMillis(),
        forceToday: Boolean = true
    ): Pair<List<CusChartData>, Float> {
        // 使用不可变列表处理空数据情况
        if (dataList.isEmpty()) {
            return Pair(
                List(BleConfig.MINUTES_IN_DAY) { CusChartData(0L, BleConfig.INVALID_VALUE) },
                0f
            )
        }

        // 计算有效心率数据的平均值
        val validHeartRates = dataList
            .map { it.value.toFloat() }
            .filter { it > 0 && isValidHeartRate(it) }
        val average = if (validHeartRates.isNotEmpty()) {
            validHeartRates.average().toFloat()
        } else {
            0f
        }

        // 使用ThreadLocal Calendar以提高性能
        val calendar = getThreadLocalCalendar()

        // 计算目标日期的开始时间
        val dayStartTime = calendar.apply {
            timeInMillis = targetDate
            setStartOfDay()
        }.timeInMillis

        // 计算源数据开始时间
        val sourceStartTime = if (forceToday) {
            dataList.firstOrNull()?.mTime?.let { time ->
                calendar.apply {
                    timeInMillis = time
                    setStartOfDay()
                }.timeInMillis
            } ?: dayStartTime
        } else {
            dayStartTime
        }

        // 预分配固定大小的数组以提高性能
        val chartData = Array(BleConfig.MINUTES_IN_DAY) {
            CusChartData(0L, BleConfig.INVALID_VALUE)
        }.apply {
            dataList.asSequence()
                .filter { it.value.toFloat() > 0 && isValidHeartRate(it.value.toFloat()) }
                .map { data ->
                    val convertedTime = if (forceToday) {
                        // 使用安全的时间计算
                        try {
                            dayStartTime + (data.mTime - sourceStartTime)
                        } catch (e: ArithmeticException) {
                            return@map null
                        }
                    } else {
                        data.mTime
                    }
                    if (convertedTime != null) data to convertedTime else null
                }
                .filterNotNull()
                .filter { (_, convertedTime) ->
                    forceToday || isValidTimestamp(convertedTime, dayStartTime)
                }
                .forEach { (data, convertedTime) ->
                    calendar.timeInMillis = convertedTime
                    val minutesFromDayStart = calculateMinutesFromDayStart(calendar)

                    if (minutesFromDayStart in 0 until BleConfig.MINUTES_IN_DAY) {
                        this[minutesFromDayStart] = CusChartData(
                            createdTime = convertedTime,
                            mValue = data.value.toFloat()
                        )
                    }
                }
        }.toList()

        return Pair(chartData, average.formatToFloat(1))
    }


    /**
     * 同一30分钟时间段内所有数据平均值
     */
    fun convertBloodOxygen(
        dataList: List<UserBloodOxygen>,
        targetDate: Long = TimeUtils.getTimeDateLong()
    ): Pair<List<CusChartData>, Float> {
        // 创建48个时间段的数据（每个时间段30分钟）
        val chartData = MutableList(48) { CusChartData(0L, BleConfig.INVALID_VALUE) }

        // 如果数据列表为空，直接返回空数组和0
        if (dataList.isEmpty()) return Pair(chartData, 0f)

        // 计算所有数据的平均值
        val totalAverage = dataList.map { it.bloodOxygen }.average().toFloat()

        // 获取目标日期的起始时间戳（00:00:00）
        val calendar = Calendar.getInstance()
        calendar.timeInMillis = targetDate
        calendar.set(Calendar.HOUR_OF_DAY, 0)
        calendar.set(Calendar.MINUTE, 0)
        calendar.set(Calendar.SECOND, 0)
        calendar.set(Calendar.MILLISECOND, 0)
        val targetDayStart = calendar.timeInMillis

        // 转换并分组数据
        dataList.map { bloodOxygen ->
            // 获取原始数据的时分秒
            calendar.timeInMillis = bloodOxygen.createdTime
            val hourOfDay = calendar.get(Calendar.HOUR_OF_DAY)
            val minute = calendar.get(Calendar.MINUTE)
            val second = calendar.get(Calendar.SECOND)

            // 将时分秒应用到目标日期
            calendar.timeInMillis = targetDayStart
            calendar.set(Calendar.HOUR_OF_DAY, hourOfDay)
            calendar.set(Calendar.MINUTE, minute)
            calendar.set(Calendar.SECOND, second)

            val adjustedTime = calendar.timeInMillis
            val minutesFromDayStart = (adjustedTime - targetDayStart) / (60 * 1000)
            val timeSlot = (minutesFromDayStart / 30).toInt()

            Pair(timeSlot, bloodOxygen)
        }
            .filter { it.first in 0..47 }
            .groupBy { it.first } // 按时间段分组
            .forEach { (timeSlot, dataList) ->
                // 计算该时间段内所有数据的平均值
                val avgBloodOxygen = dataList.map { it.second.bloodOxygen }.average().toInt().toFloat()
                // 使用最后一条数据的时间戳
                val lastCreatedTime = dataList.maxOf { it.second.createdTime }

                chartData[timeSlot] = CusChartData(
                    createdTime = lastCreatedTime,
                    mValue = avgBloodOxygen,
                    minValue = avgBloodOxygen - Random.nextInt(0, 28)
                )
            }

        return Pair(chartData, totalAverage.formatToFloat(1))
    }
}